#!/bin/sh
#
# Copyright (c) 2007-2009 The PureDarwin Project.
# All rights reserved.
#
# @LICENSE_HEADER_START@
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
# 1. Redistributions of source code must retain the above copyright
#    notice, this list of conditions and the following disclaimer.
# 2. Redistributions in binary form must reproduce the above copyright
#    notice, this list of conditions and the following disclaimer in the
#    documentation and/or other materials provided with the distribution.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
# IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
# THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
# PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
# PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
# LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#
# @LICENSE_HEADER_END@
#

#
# Copyright (c) 2005, Apple Computer, Inc. All rights reserved.
#
# @APPLE_BSD_LICENSE_HEADER_START@
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
# 1.  Redistributions of source code must retain the above copyright
#     notice, this list of conditions and the following disclaimer.
# 2.  Redistributions in binary form must reproduce the above copyright
#     notice, this list of conditions and the following disclaimer in the
#     documentation and/or other materials provided with the distribution.
# 3.  Neither the name of Apple Computer, Inc. ("Apple") nor the names of
#     its contributors may be used to endorse or promote products derived
#     from this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND
# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
# ARE DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR
# ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
# STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
# IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.
#
# @APPLE_BSD_LICENSE_HEADER_END@
#

#
# probono <probono@puredarwin.org>
# aladin   <aladin@puredarwin.org>
#

#
# Unpack, thin and pack "vital" BinaryRoots and BinaryDrivers
#
# 	Usage: pd_thin
#
# This script runs in a directory containing binary roots 
# produced by DarwinBuild. It will create a subdirectory
# which will contain tar.bz2 packages thinned to the specified architecture.
#
# Based on thinPackages.sh by:
#
# Kevin Van Vechten <kvv@apple.com>
#

#
# Changelog (deprecated)
# 
# 20090326 - Please, see `hg log' or `svn log' from now (Mercurial) - aladin
# 20081209 - License header update - aladin
# 20081115 - Minor updates - aladin
# 20080831 - Minor updates - aladin
# 20080803 - Loops merged (binary roots and drivers) - aladin
# 20080522 - Cleanup, gave way too many errors - probono
# 20080303 - Minor updates - aladin
# 20080107 - Adoption and rewrite for PureDarwin - probono
#

################################################################################
# GLOBAL VARIABLES
################################################################################

# Find out where this script lives
DIRNAME=$(cd $(dirname $0) && pwd)

# Reading global variables in pd_config file
source "$DIRNAME"/pd_config

################################################################################
# INITIAL CONDITION
################################################################################

# Autorun
if [ "$1" = "" ]; then
	echo
	echo "Thin "vital" binary files (roots and drivers)."
	echo
	echo "Legend:"
	echo " . project.root.tar.gz\tThe archive has already been thinned"
	echo " * project.root.tar.gz\tThe archive has just been thinned "
	echo " ? project.root.tar.gz\tThe archive is missing" 

	echo
	echo "Thinning binaryroots, please wait..."

	# Recursive call of itself
	$0 0 `cat $BINARYROOTS_LIST_FILE $BINARYROOTS_EXTRA_LIST_FILE`
	exit 0
fi

################################################################################
# OTHER VARIABLES
################################################################################

# Recursive level found in arg1 (loop counter)
LEVEL=$1
# Current build version target taken in BINVERSION array from pd_config
BUILD_VERSION=${BINVERSION[$LEVEL]}

# Eating args $1 
#
# 	Shifting LEVEL
#       $# (arg0..argn) is now the list of missing binary files (from pd_roots file)
#
#	At the beginning, all the files are missing
#	At the end, no file should missing
shift

################################################################################
# RECURSIVE CONDITIONS
################################################################################

# Break condition: no more missing files found in args, success.
if [ $# -eq 0 ]; then
	echo
	echo "Thinning binary files complete ($MISSING_LIST_INIT files)" 
	if [ "$BAD_SHA1_LIST" ]; then
		echo "WARNING! SHA-1 checksum failed on:$BAD_SHA1_LIST"
	fi	
	exit 0
fi

# Break condition: no more level to go in, end of array, some missing files could remain..
if [ $LEVEL -gt $[${#BINVERSION[@]} - 1] ]; then
	echo 
	echo "Thinning binary files uncomplete"
	echo "Missing $[$MISSING_LIST_INIT - $[$MISSING_LIST_INIT - $#]] files: $*"
	if [ "$BAD_SHA1_LIST" ]; then
		echo "WARNING! SHA-1 checksum failed on:$BAD_SHA1_LIST"
	fi	
	exit -1
fi

# Initialization, level 0 is the beginning
if [ $LEVEL -eq 0 ]; then
	# As `cat pd_roots | wc -l` (because all files are missing)
	MISSING_LIST_INIT=$#
	export BAD_SHA1_LIST=""
fi


function thinfile {
if lipo "$2" -verify_arch "$1" 2>/dev/null ; then
    MODES=$(/usr/bin/stat -f%p "$2" | cut -b3-6)

    if [ ! $VERBOSE = "" ]; then
    	echo "   Thinning $(basename \"$2\") to \"$1\""
    fi

    lipo "$2" -thin "$1" -output "$2" 2> /dev/null
    # we could even remove .o .a .h .c and other Developer files and put them in a -dev package
    chmod "$MODES" "$2"

    printf "."
fi
}

################################################################################
# MAIN
################################################################################

# Matching condition: current build version does belong to the target darwin release
MAJOR_BUILD_VERSION=`echo $BUILD_VERSION | cut -b1-"$(printf "$DARWIN_RELEASE" | wc -c | sed 's/ //g')"`
# Faking major build version for specific build version "pd" (mostly binaryroots for Darwin 9)
if [ "$BUILD_VERSION" = "pd" ]; then
	MAJOR_BUILD_VERSION="$DARWIN_RELEASE"
fi
if [ "$DARWIN_RELEASE" =  "$MAJOR_BUILD_VERSION" ]; then

	echo
	echo "BuildVersion: $BUILD_VERSION ($[$MISSING_LIST_INIT - $#]/$MISSING_LIST_INIT files)"

	for x in $*; do

		B_THIN_BINARYROOT=""
		BINARYROOT_FOUND=""

		###############################################################
		# LOCAL BINARYROOT
		###############################################################
		if [ "$BINARYROOT_FOUND" = "" ]; then
			# Test missing binary file existence in the local target dir ($BINARYROOTS_DEFAULT_DIR)
			if [ -e "$BINARYROOTS_DEFAULT_DIR/$BUILD_VERSION/${x}.root.tar.gz" ]; then
				#echo " . ${x}.root.tar.gz"
				BINARYROOT_FOUND="$BINARYROOTS_DEFAULT_DIR/$BUILD_VERSION/${x}.root.tar.gz"
			fi
		fi

		###############################################################
		# LOCAL EXTRA BINARYROOT
		###############################################################
		if [ "$BINARYROOT_FOUND" = "" ]; then
			# Test missing binary file existence in the local build directories
			z=0
			while [ $z -lt $[${#BINARYROOTS_DIR[@]}] ]; do
				BINARY_DIR=${BINARYROOTS_DIR[$z]}
				if [ -e "$BINARY_DIR/$BUILD_VERSION/${x}.root.tar.gz" ]; then
					#echo " . ${x}.root.tar.gz"
					BINARYROOT_FOUND="$BINARY_DIR/$BUILD_VERSION/${x}.root.tar.gz"
					break # FIXME: It stops at the first one found
				fi	
			z=$[$z + 1]
			done # End of WHILE through BINARYROOTS_DIR
		fi

		###############################################################
		# LOCAL DARWINBUILD BINARYROOT
		###############################################################
		if [ "$BINARYROOT_FOUND" = "" ]; then
			# Test missing binary file existence in the darwinbuild build directory
			DARWINBUILD_BUILD_DIR_FOUND=""
			for DARWINBUILD_BUILD_DIR in `ls $DARWINBUILD_DIR`; do
				if [ -e "$DARWINBUILD_DIR/$DARWINBUILD_BUILD_DIR/.build/build" ]; then
					DARWINBUILD_BUILD_DIR_BUILDVERSION=`cat $DARWINBUILD_DIR/$DARWINBUILD_BUILD_DIR/.build/build 2> /dev/null`
					if [ "${BINVERSION[$LEVEL]}"  = "$DARWINBUILD_BUILD_DIR_BUILDVERSION" ]; then
						DARWINBUILD_BUILD_DIR_FOUND=$DARWINBUILD_DIR/$DARWINBUILD_BUILD_DIR
						break # FIXME: It stops at the first one found
					fi
				fi
			done
			if [ ! "$DARWINBUILD_BUILD_DIR_FOUND" = "" ]; then
				DARWINBUILD_BINARYROOT_FOUND=""
				if [ -e $DARWINBUILD_BUILD_DIR_FOUND/Roots/.DownloadCache/${x}.root.tar.gz ]; then
					# Took first from ../Roots/.DownloadCache/.. which content is == fetching it remotely in case this step fail to found
					DARWINBUILD_BINARYROOT_FOUND="$DARWINBUILD_BUILD_DIR_FOUND/Roots/.DownloadCache/${x}.root.tar.gz"
				else
					# Then took from ../Packages/..
					if [ -e $DARWINBUILD_BUILD_DIR_FOUND/Packages/${x}.root.tar.gz ]; then
						DARWINBUILD_BINARYROOT_FOUND="$DARWINBUILD_BUILD_DIR_FOUND/Packages/${x}.root.tar.gz"
					fi
				fi
			fi
			if [ ! $DARWINBUILD_BINARYROOT_FOUND = "" ]; then
				#echo " + ${x}.root.tar.gz"
				BINARYROOT_FOUND=$DARWINBUILD_BINARYROOT_FOUND
			fi
		fi

		###############################################################
		# THINNING BINARYROOT IF NEEDED 
		###############################################################
		if [ ! "$BINARYROOT_FOUND" = "" ]; then 
			B_THIN_BINARYROOT=$BINARYROOT_FOUND
			mkdir -p "$DESTDIR"
				Y=$(basename $B_THIN_BINARYROOT .gz).bz2
				if [ $B_THIN_BINARYROOT -nt $DESTDIR/$Y ]; then
					printf " * $(basename $B_THIN_BINARYROOT) ."
					rm -rf "$DESTDIR/tmp"
					printf "."
					mkdir -p "$DESTDIR/tmp"
					printf "."
					tar xzf $B_THIN_BINARYROOT -C "$DESTDIR/tmp"
					if [ $? -eq 0 ]; then
						printf "."
						for file in $(find "$DESTDIR/tmp/" -type f); do
							thinfile "$ARCH" "$file"
						done
						printf "."
						tar cjf "$DESTDIR/$Y" -C "$DESTDIR/tmp" .
						echo ""
					else
						#echo " ! $DESTDIR/$Y (Corrupted archive)"
						echo " (Corrupted archive)"
					fi
					
				else
					echo " . $Y"
				fi
			rm -rf "$DESTDIR/tmp"
		fi

		###############################################################
		# MISSING BINARYROOT 
		###############################################################
		if [ "$BINARYROOT_FOUND" = "" ]; then
			echo " ? ${x}.root.tar.gz";
			#####rm -f $BINARYROOTS_DEFAULT_DIR/$BUILD_VERSION/${x}.root.tar.gz
			# Adding missing binary to missing binary list
			MISSING_LIST="${MISSING_LIST} ${x}"
		fi	
			
	done # End of FOR through missing binaryroots list (MISSING_LIST)
else
	#echo "Skipping. Major build version ($MAJOR_BUILD_VERSION (build ver: $BUILD_VERSION)) does not match Major Darwin release ($DARWIN_RELEASE)."
	# Adding initial missing binary to missing binary list since no current BuildVersion directory has been found
	MISSING_LIST="$*"
fi

################################################################################
# RECURSIVE CALL
################################################################################

# Recursive call + propagating MISSING_LIST_INIT in env
MISSING_LIST_INIT="$MISSING_LIST_INIT" $0 $[$LEVEL + 1] $MISSING_LIST

exit 0
